package com.njzdr.common;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.ArrayMap;

import com.coszero.utilslibrary.utils.LogX;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Desc： 蓝牙开发管理类
 * - 使用蓝牙需要申请权限,
 * # android.permission.BLUETOOTH
 * # android.permission.BLUETOOTH_ADMIN
 * # android.permission.ACCESS_FINE_LOCATION"
 * (如果您的应用针对 Android 9或更低，您可以改为声明   ACCESS_COARSE_LOCATION)
 * <p>
 * - 用于判断蓝牙是否可用
 * - 搜索附近蓝牙设备,包含低功耗蓝牙搜索和经典蓝牙搜索
 * - 获取系统以配对蓝牙列表
 *
 * @author xmqian
 * Email:xmqian93@163.com
 * Date: 2020/10/27 0027 17:56
 * @version 1.0.1
 */
public class BluetoothManager {
    private static final String TAG = "bluetooth";
    /**
     * 开启蓝牙请求码,如果需要开启回调可以使用此值在
     * onActivityResult()方法中捕捉
     */
    public static final int REQUEST_ENABLE_BT = 222;
    // 蓝牙扫描超时时间/毫秒
    private static final long SCAN_TIMEOUT = 10000;

    private BluetoothAdapter mAdapter;
    private static BluetoothManager instance;
    /**
     * 过滤重复搜到的蓝牙
     */
    private final Map<String, BluetoothDevice> mFilterBluetoothMap = new ArrayMap<>();
    /**
     * ble蓝牙扫描状态,true:正在扫描,false:扫描停止
     */
    private boolean bleIsScanning;

    /**
     * 是否注册经典蓝牙的扫描监听
     * - true:已注册 false:未注册
     */
    private boolean isRegisterReceiver;
    /**
     * 蓝牙监听广播
     */
    private BluetoothReceiver bluetoothReceiver;
    /**
     * 蓝牙扫描监听回调
     */
    private BluetoothScanListner scanListner;
    private final Handler mHandler = new Handler(Looper.myLooper());
    /**
     * 低功耗蓝牙扫描结果回调
     */
    private ScanCallback leScanCallback;


    public static BluetoothManager getInstance() {
        if (instance == null) {
            instance = new BluetoothManager();
        }
        return instance;
    }

    private BluetoothManager() {
        getmAdapter();
    }

    /**
     * @return 返回蓝牙适配器
     */
    public BluetoothAdapter getmAdapter() {
        if (mAdapter == null) {
            mAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        return mAdapter;
    }

    /**
     * 检查蓝牙
     * 判断蓝牙是否打开
     * 判断是否支持蓝牙
     */
    public boolean checkBluetooth(Activity activity) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        //为null说明设备不支持蓝牙
        if (null != mAdapter) {
            //尝试打开蓝牙
            if (!mAdapter.isEnabled()) {
                LogX.i(TAG, "蓝牙未开启,正在开启蓝牙");
                openBluetooth(activity);
            }
            return true;
        }
        LogX.e(TAG, "设备不支持蓝牙");
        return false;
    }

    /**
     * 打开蓝牙
     *
     * @param mActivity activity,如果需要开启回调,可在activity中使用onResult
     */
    public void openBluetooth(Activity mActivity) {
        if (mAdapter != null) {
            if (!mAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                mActivity.startActivityForResult(intent, REQUEST_ENABLE_BT);
            }
        }
    }

    /**
     * 打开蓝牙,无结果返回
     */
    public void openBluetoothNoResult() {
        if (mAdapter != null) {
            if (!mAdapter.isEnabled()) {
                mAdapter.enable();
            }
        }
    }

    /**
     * 判断蓝牙是否已开启,并是否可用
     *
     * @return 是否蓝牙已准备好
     */
    public boolean isAdapterReady() {
        return (mAdapter != null) && (mAdapter.isEnabled());
    }

    /**
     * 得到已经配对的列表
     *
     * @return 已配对蓝牙列表
     */
    public List<BluetoothDevice> getPairDeviceList() {
        List<BluetoothDevice> list = new ArrayList<>();
        if (mAdapter != null) {
            Set<BluetoothDevice> mSet = getmAdapter().getBondedDevices();
            final Iterator mIterator = mSet.iterator();
            while (mIterator.hasNext()) {
                BluetoothDevice bluetoothDevice = (BluetoothDevice) mIterator.next();
                list.add(bluetoothDevice);
            }
        }
        return list;
    }

    /**
     * 动态注册广播监听
     */
    public void registerBoradcastReceiver(Activity mActivity) {
        if (!isRegisterReceiver) {
            isRegisterReceiver = true;
            bluetoothReceiver = new BluetoothReceiver();
            List<IntentFilter> filterList = new ArrayList<>();
            //蓝牙状态监听,蓝牙关闭,蓝牙开启,蓝牙正在关闭,蓝牙正在开启
            filterList.add(new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
            //搜索广播
            filterList.add(new IntentFilter(BluetoothDevice.ACTION_FOUND));
            //搜索结束
            filterList.add(new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
            //断开连接
            filterList.add(new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
            //连接
            filterList.add(new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
            //请求配对
            filterList.add(new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));
            //配对状态
            filterList.add(new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));

            for (IntentFilter intentFilter : filterList) {
                mActivity.registerReceiver(bluetoothReceiver, intentFilter);
            }

            //设置回调监听
            bluetoothReceiver.setScanListner(new BluetoothScanListner() {
                @Override
                public void scanStart(boolean isSuccess) {
                }

                @Override
                public void scanResult(BluetoothDevice device) {
                    if (scanListner != null) {
                        scanListner.scanResult(device);
                        if (!mFilterBluetoothMap.containsKey(device.getAddress())) {
                            mFilterBluetoothMap.put(device.getAddress(), device);
                            //将过滤好的蓝牙列表返回
                            scanListner.scanResult(new ArrayList<>(mFilterBluetoothMap.values()));
                        }
                    }
                }

                @Override
                public void scanResult(List<BluetoothDevice> deviceList) {

                }

                @Override
                public void scanFinish() {
                    if (scanListner != null) {
                        scanListner.scanFinish();
                    }
                }
            });
        }
    }

    /**
     * 取消注册广播
     */
    public void unregisterReceiver(Activity mActivity) {
        if (isRegisterReceiver) {
            isRegisterReceiver = false;
            if (bluetoothReceiver != null) {
                mActivity.unregisterReceiver(bluetoothReceiver);
                bluetoothReceiver = null;
                scanListner = null;
                //取消注册广播时,停止扫描蓝牙
                if (mAdapter.isDiscovering()) {
                    mAdapter.cancelDiscovery();
                }
            }
        }
    }

    /**
     * 发现蓝牙
     * - 必须在执行发现前先停止发现
     */
    public void scan(BluetoothScanListner scanListner) {
        this.scanListner = scanListner;
        if (isAdapterReady()) {
            scanListner.scanStart(true);
            mFilterBluetoothMap.clear();
            if (mAdapter.isDiscovering()) {
                //如果正在发现,就取消发现,等500毫秒再次扫描
                mAdapter.cancelDiscovery();
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //这里防止被重复点击,如果多个延迟,只执行一个
                        if (mAdapter.isDiscovering()) {
                            return;
                        } else {
                            mAdapter.startDiscovery();
                        }
                    }
                }, 500);
            } else {
                mAdapter.startDiscovery();
            }
        } else {
            scanListner.scanStart(false);
        }
    }

    /**
     * 低功耗蓝牙扫描,仅支持扫描低功耗蓝牙,扫描不到经典蓝牙
     * - 不能在30秒内连续扫描停止超过5次,否则会扫描不到蓝牙,建议扫描结束到下一次扫描增加延迟
     * - 安卓4.3开始支持BLE功能(仅支持中心模式,客户端模式)
     * - 安卓5.0开始支持(外设模式,服务端模式)
     */
    public void bleScan(final BluetoothScanListner scanListner) {
        if (isAdapterReady()) {
            if (!bleIsScanning) {
                if (Build.VERSION.SDK_INT >= 21) {
                    bleIsScanning = true;
                    scanListner.scanStart(true);
                    mFilterBluetoothMap.clear();
                    //获取扫描对象,蓝牙未启用返回null
                    final BluetoothLeScanner bluetoothLeScanner = mAdapter.getBluetoothLeScanner();

                    //蓝牙扫描结果回调
                    leScanCallback = new ScanCallback() {
                        @Override
                        public void onScanResult(int callbackType, ScanResult result) {
                            BluetoothDevice device = result.getDevice();
                            //信号强度
                            int rssi = result.getRssi();
                            scanListner.scanResult(device);
                            if (!mFilterBluetoothMap.containsKey(device.getAddress())) {
                                mFilterBluetoothMap.put(device.getAddress(), device);
                                //将过滤好的蓝牙列表返回
                                scanListner.scanResult(new ArrayList<>(mFilterBluetoothMap.values()));
                            }
                        }
                    };

                    //设置蓝牙扫描超时时间
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            bleIsScanning = false;
                            scanListner.scanFinish();
                            bluetoothLeScanner.stopScan(leScanCallback);
                        }
                    }, SCAN_TIMEOUT);

                    //开始扫描
                    bluetoothLeScanner.startScan(leScanCallback);

                    return;
                }
            }
        }
        scanListner.scanStart(false);
    }

    /**
     * 停止扫描
     */
    public void stopScan() {
        if (isAdapterReady()) {
            if (mAdapter.isDiscovering()) {
                mAdapter.cancelDiscovery();
            }
        }
    }

    /**
     * 停止ble蓝牙扫描
     */
    public void stopBleScan() {
        if (Build.VERSION.SDK_INT >= 21) {
            if (isAdapterReady()) {
                if (bleIsScanning) {
                    bleIsScanning = false;
                    BluetoothLeScanner bluetoothLeScanner = mAdapter.getBluetoothLeScanner();
                    if (leScanCallback != null) {
                        bluetoothLeScanner.stopScan(leScanCallback);
                    }
                }
            }
        }
    }
}
